<template>
	<section
		class="preview-box"
		ref="wrap"
	>
		<!-- 图片拖拽部分 -->
		<div
			ref="imgWrap"
			class="relative z-10 drag"
			@click="maskClosable && handleCloseClick()"
		>
			<img
				@click.stop
				ref="imgRef"
				:src="currentSrc"
				draggable="false"
				class="preview-img"
				:style="{
					transformOrigin: 'center',
					transition: 'transform 0.2s',
					transform: `rotate(${rotate}deg) scale3d(${scaleX}, ${scaleY}, 1)`
				}"
			/>
		</div>

		<!-- 蒙层 -->
		<div
			v-if="mask"
			class="mask"
			@click="maskClosable && handleCloseClick()"
			:style="{ background: maskBackground }"
		></div>

		<!-- 操作按钮栏 -->
		<div class="operate-button">
			<template v-if="group?.length">
				<CaretLeftOutlined
					@click="handleSwitchBtnClick('left')"
					class="cursor-pointer"
				/>
				<div class="flex items-center flex-shrink-0 mx-5 select-none text-15">
					{{ currentIndex + 1 }} / {{ group.length }}
				</div>
				<CaretRightOutlined
					@click="handleSwitchBtnClick('right')"
					class="cursor-pointer"
				/>
			</template>
			<SwapOutlined
				class="rotate-90"
				@click="handleTurnBtnClick('y')"
			/>
			<SwapOutlined @click="handleTurnBtnClick('x')" />
			<RotateLeftOutlined @click="rotate -= 90" />
			<RotateRightOutlined @click="rotate += 90" />
			<ZoomOutOutlined @click="handleScaleBtnClick(-0.5)" />
			<ZoomInOutlined @click="handleScaleBtnClick(0.5)" />
			<OneToOneOutlined @click="handleRsesetClick" />
			<CloseCircleOutlined @click="handleCloseClick" />
		</div>
	</section>
</template>

<script setup lang="ts">
import { useDrag } from '@/hooks'
import {
	CaretLeftOutlined,
	CaretRightOutlined,
	CloseCircleOutlined,
	OneToOneOutlined,
	RotateLeftOutlined,
	RotateRightOutlined,
	SwapOutlined,
	ZoomInOutlined,
	ZoomOutOutlined
} from '@ant-design/icons-vue'
import { useEventListener } from '@vueuse/core'
import type { Preview } from './index.d'

const {
	src,
	group = [],
	mask = true,
	escCloseable = true,
	maskClosable = true,
	maskBackground = 'rgba(0, 0, 0, 0.45)',
	lockBodyScroll = true
} = defineProps<Preview>()

// 操作按钮相关
const rotate = ref(0)
const scaleX = ref(1)
const scaleY = ref(1)
const handleScaleBtnClick = (num: number) => {
	const x = scaleX.value
	const y = scaleY.value
	if (num < 0 && Math.abs(scaleX.value) <= 0.5) return
	scaleX.value = x > 0 ? x + num : -(Math.abs(x) + num)
	scaleY.value = y > 0 ? y + num : -(Math.abs(y) + num)
}
const handleTurnBtnClick = (type: 'x' | 'y') => {
	if (type === 'x') scaleX.value = -scaleX.value
	if (type === 'y') scaleY.value = -scaleY.value
}

const imgWrap = ref<HTMLDivElement>()
const { resetDrag, removeDragListener } = useDrag(imgWrap)
const handleRsesetClick = () => {
	scaleX.value = 1
	scaleY.value = 1
	rotate.value = 0
	resetDrag()
}

// 切换图片相关操作
const currentSrc = ref(src)
const currentIndex = ref(group.findIndex(item => item === src))
const handleSwitchBtnClick = (direction: 'left' | 'right') => {
	const len = group?.length
	const cur = currentIndex.value
	if (direction === 'right') {
		currentIndex.value = cur + 1 >= len ? 0 : ++currentIndex.value
	} else if (direction === 'left') {
		currentIndex.value = cur === 0 ? len - 1 : --currentIndex.value
	}
	currentSrc.value = group[currentIndex.value]
	handleRsesetClick()
}

// 关闭图片预览相关
const wrap = ref<HTMLDivElement>()
let removeKeydownListener: Function
let removeWheelListener: Function

removeKeydownListener = useEventListener(document, 'keydown', (event: KeyboardEvent) => {
	if (event.key === 'Escape') escCloseable && handleCloseClick()
})
const imgRef = ref<HTMLImageElement>()

removeWheelListener = useEventListener(imgRef, 'wheel', (event: WheelEvent) => {
	event.deltaY > 0 ? handleScaleBtnClick(0.1) : handleScaleBtnClick(-0.1)
})

const handleCloseClick = () => {
	removeDragListener()
	setBodyOverflow('auto')
	removeKeydownListener && removeKeydownListener()
	removeWheelListener && removeWheelListener()
	const parentNode = wrap.value?.parentNode as HTMLElement
	parentNode.remove()
}

lockBodyScroll && setBodyOverflow('hidden')
function setBodyOverflow(value: 'hidden' | 'auto') {
	// document.body.style.overflow = value
}
</script>

<style scoped lang="less">
.preview-box {
	position: fixed;
	left: 0;
	top: 0;
	bottom: 0;
	right: 0;
	display: flex;
	justify-content: center;
	align-items: center;
	z-index: 9999;
}

.preview-img {
	max-width: 800px;
	height: auto;
	animation: scale 0.1s ease-out;
	user-select: none;
}

.mask {
	animation: fade 0.1s;
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
}

@keyframes fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@keyframes scale {
	from {
		transform: scale(0.4);
	}
	to {
		transform: scale(1);
	}
}

.operate-button {
	display: flex;
	border-radius: 6px;
	font-size: 18px;
	background: #fff;
	position: fixed;
	bottom: 20px;
	color: rgba(0, 0, 0, 0.9);
	z-index: 1000;
	overflow: hidden;
}

:deep(.anticon) {
	display: inline-block;
	padding: 14px;

	&:hover {
		background: rgba(0, 0, 0, 0.1);
	}
}
</style>
